<?php
/**
 * Created by PhpStorm.
 * User: leixiaotian
 * Date: 2020/9/29
 * Time: 14:33
 */
namespace App\Http\Controllers\Api;

use Illuminate\Http\Request;
use App\Http\Services\Oss;
use Illuminate\Support\Facades\DB;
use mysql_xdevapi\Exception;

class ChatLogsController extends BaseController
{
    const REQUEST_URL = 'https://api-cn.ronghub.com/message/history.json';
    const APP_SECRET = 's8MWKVT4u5to88';
    const APP_Key = 'tdrvipkstyqj5';

    protected $table = 'chat_log';
    protected $publicLogTable = 'chatpublic_log';

    public function __construct(Request $request)
    {
        parent::__construct($request);
    }

    //从融云下载历史消息（单聊）
    public function downloadLogs(int $hour)
    {
        ignore_user_abort();
        set_time_limit(0);

        //获取前一个小时的记录
        $dates = $hour?date('YmdH', $hour):date('YmdH', strtotime('-1 hour'));
        $zipDates = $hour?date('Y-m-d-H', $hour):date('Y-m-d-H', strtotime('-1 hour'));
        $timestamp = time() * 1000; //毫秒数
//        var_dump($dates);
        $data['appSecret'] = self::APP_SECRET;
        $data['App-Key'] = self::APP_Key;
        $data['Nonce'] = rand();
        $data['Timestamp'] = $timestamp;

        $sign = $this->generateSignature($data);
        $data['Signature'] = $sign;

        $requestData['date'] = $dates;

        $httpHeader[] = 'App-Key:'.$data['App-Key'];
        $httpHeader[] = 'Nonce:'.$data['Nonce'];
        $httpHeader[] = 'Timestamp:'.$timestamp;
        $httpHeader[] = 'Signature:'.$sign;

        $res = curl_request(self::REQUEST_URL, $requestData,'urlencoded','POST', $httpHeader);

        if($res['code'] != 200) {
            write_log('requestRongYun', 'error', $res);
        }else {
            //todo 判断请求成功但是url为空的情况
            if(!$res['url']) {
                return false;
            }
//            var_dump($res['url']);
            $publicPath = public_path();
            //url不为空
            $downRes = $this->getFile($res['url'], $publicPath, $dates);
            if($downRes) {
                $path = $publicPath."/".$dates.'.zip';
//                var_dump($path);

                //解压文件
                $unzipRes = $this->unzip_file($path, $publicPath);
                if($unzipRes != 'success') {
                    return false;
                }

                //todo 打开文件一行一行处理
                $this->handleFile($publicPath, $zipDates);

                $path1 = $publicPath.'/'.$zipDates;
                $path2 = $publicPath.'/'.$dates.'.zip';
                unlink($path1);
                unlink($path2);
            }else {
                return false;
            }
        }
    }

    //从融云下载历史消息（公屏聊天）
    public function downloadLogsOfPublic()
    {
        ignore_user_abort();
        set_time_limit(0);

        //获取前一个小时的记录
        $dates = date('YmdH', strtotime("-1 hour"));
        $zipDates = date('Y-m-d-H', strtotime("-1 hour"));

        $timestamp = time() * 1000; //毫秒数

        $data['appSecret'] = self::APP_SECRET;
        $data['App-Key'] = self::APP_Key;
        $data['Nonce'] = rand();
        $data['Timestamp'] = $timestamp;

        $sign = $this->generateSignature($data);
        $data['Signature'] = $sign;

        $requestData['date'] = $dates;

        $httpHeader[] = 'App-Key:'.$data['App-Key'];
        $httpHeader[] = 'Nonce:'.$data['Nonce'];
        $httpHeader[] = 'Timestamp:'.$timestamp;
        $httpHeader[] = 'Signature:'.$sign;

        $res = curl_request(self::REQUEST_URL, $requestData,'urlencoded','POST', $httpHeader);

        if($res['code'] != 200) {
            write_log('requestRongYun', 'error', $res['errorMessage']);
        }else {
            //todo 判断请求成功但是url为空的情况
            if($res['url'] == '') {
                return 0;
            }

            $publicPath = public_path();
            //url不为空
            $downRes = $this->getFile($res['url'], $publicPath, 'public'.$dates);
            if($downRes) {
                $path = $publicPath."/public".$dates.'.zip';

                //解压文件
                $unzipRes = $this->unzip_file($path, $publicPath.'/public'.$dates);
                if($unzipRes != 'success') {
                    return 0;
                }

                //todo 打开文件一行一行处理
                $this->handleFilePublic($publicPath.'/public'.$dates, $zipDates);

                $path1 = $publicPath.'/public'.$dates;
                $path2 = $publicPath.'/public'.$dates.'.zip';
                $this->deldir($path1);
                unlink($path2);
            }else {
                return 0;
            }
        }
    }

    //删除指定文件夹以及文件夹下的所有文件
    function deldir($dir) {
        //先删除目录下的文件：
        $dh=opendir($dir);
        while ($file=readdir($dh)) {
            if($file!="." && $file!="..") {
                $fullpath=$dir."/".$file;
                if(!is_dir($fullpath)) {
                    unlink($fullpath);
                } else {
                    deldir($fullpath);
                }
            }
        }

        closedir($dh);
        //删除当前文件夹：
        if(rmdir($dir)) {
            return true;
        } else {
            return false;
        }
    }

    //清除15天前的历史聊天记录
    public function removeChat()
    {
        $dateTime = date("Y-m-d H:i:s", strtotime("-15 days"));
        DB::table($this->table)->where('dateTime', '<', $dateTime)->delete();
    }

    //清除15天前的公屏历史聊天记录
    public function removeChatPublic()
    {
        $dateTime = strtotime("-15 days");
        DB::table($this->publicLogTable)->where('dateTime', '<', $dateTime)->delete();
    }

    //生成签名
    private function generateSignature($data)
    {
        return sha1($data['appSecret'].$data['Nonce'].$data['Timestamp']);
    }

    //处理文件
    public function handleFile($publicPath, $fileName)
    {
        $path = $publicPath."/".$fileName;
        $handle = fopen($path, "r");  //打开文件

        $line = '';
        while( !feof($handle) )
        {
            $c = fgetc($handle); //一个字符一个字符读取文件内容
            $line .= $c;

            if ( preg_match("#[\r\n]+#", $c) )   //当遇到换行符时则取出内容
            {
                try{
                $line_content = $line;  //line 一行内容
                $line = '';  //把一行的内容清空

                //截取掉日期内容
                $line_content = substr($line_content, 19);
                $content = json_decode($line_content, true);
                if (is_numeric( $content['fromUserId'] ) && is_numeric($content['targetId']) && isset($content['content']['content']) ){
                    //todo 只处理单聊
                    if ($content['targetType'] == 1) {
                        if ($content['classname'] == 'RC:TxtMsg' || $content['classname'] == 'RC:ImgMsg' || $content['classname'] == 'RC:VcMsg') {
                            //包含OPEN_说明是个播消息
                            if (strpos($content['fromUserId'], 'OPEN_') !== false) {
                                continue;
                            }
                            if (strpos($content['targetId'], 'OPEN_') !== false) {
                                continue;
                            }
                            $data['user_id'] = $content['fromUserId'];
                            $data['to_user_id'] = $content['targetId'];
                            $data['chat_type'] = $content['classname'];
                            $data['content'] = base64_encode($content['content']['content']);
                            $data['dateTime'] = $content['dateTime'];

                            //图片消息
                            if ($content['classname'] == 'RC:ImgMsg') {
                                $data['content'] = $content['content']['imageUri'];
                            }

                            //语音消息
                            if ($content['classname'] == 'RC:VcMsg') {
                                $voiceContent = $content['content']['content'];
                                $voiceContent = base64_decode($voiceContent);
                                $res = $this->uploadVoice($voiceContent, 'amr');
                                $data['content'] = $res ?? '上传失败';
                            }
                            try{
                                DB::table($this->table)->insert($data);
                            }catch (\Exception $e){
                                continue;
                            }
                        }
                    }
                }
                }catch (\Exception $e){
                    continue;
                }
            }

        }

        fclose($handle); // 关闭文件
    }

    public function handleFilePublic($publicPath, $fileName)
    {
        $path = $publicPath."/".$fileName;
        $handle = fopen($path, "r");  //打开文件

        $line = '';
        while( !feof($handle) )
        {
            try {
            $c = fgetc($handle); //一个字符一个字符读取文件内容
            $line .= $c;

            if ( preg_match("#[\r\n]+#", $c) )   //当遇到换行符时则取出内容
            {
                $line_content = $line;  //line 一行内容
                $line = '';  //把一行的内容清空

                //截取掉日期内容
                $line_content = substr($line_content, 19);
                $content = json_decode($line_content, true);
                //todo 处理聊天室会话
                if (is_numeric( $content['fromUserId'] ) && is_numeric($content['targetId']) && isset($content['content']['content'])) {
                    if($content['targetType'] == 4) {
                        if($content['classname'] == 'RC:TxtMsg' || $content['classname'] == 'RC:ImgMsg') {
                            $data['user_id'] = $content['fromUserId'];
                            $data['to_user_id'] = $content['targetId'];
                            $data['chat_type'] = $content['classname'];
                            $data['content'] = base64_encode($content['content']['content']);
                            $data['dateTime'] = strtotime($content['dateTime']);

                            //图片消息
                            if($content['classname'] == 'RC:ImgMsg') {
                                $data['content'] = $content['content']['imageUri'];
                            }
                            try {
                                DB::table($this->publicLogTable)->insert($data);
                            }catch (Exception $e){
                                continue;
                            }
                        }
                    }
                }
            }
        }catch (Exception $e){
            continue;
        }
        }

        fclose($handle); // 关闭文件
    }

    /**
     * @param $content  文件内容
     * @param $ext   文件后缀
     */
    private function uploadVoice($content, $ext)
    {
        $oss = new Oss();
        $upload_config = $this->get_oss_config(14, $ext);  //14： api那边规定 用来指定目录;
        $ossRes = $oss->getAs($upload_config['data'][0]['put_url'], $content);
        if (!$ossRes) {
            return false;
        }

        return $upload_config['data'][0]['uri'];
    }

    private function unzip_file($file, $destination){
        // 实例化对象
        $zip = new \ZipArchive() ;
        //打开zip文档，如果打开失败返回提示信息
        if ($zip->open($file) !== TRUE) {
            return 'Could not open archive';
        }
        //将压缩文件解压到指定的目录下
        $zip->extractTo($destination);
        //关闭zip文档
        $zip->close();
        return 'success';
    }

    /**
     * 获取阿里云文件上传参数
     * @return mixed
     */
    private function get_oss_config(int $type = 1, string $ext = 'jpg')
    {
        $res = curl_request(config('kkaudio.kkaudio_api') . "/inner/system/put_file_url", ['type' => $type, 'exts' => $ext, 'noase' => 1], $contentType = 'urlencoded', $httpMethod = 'GET');
        if ($res['code'] == 0) {
            return $res;
        }
        return '';
    }

    private function getFile($url,$path='',$filename='',$type=0){
        if($url==''){return 0;}
        //获取远程文件数据
        if($type===0){
            $ch=curl_init();
            $timeout=30;
            curl_setopt($ch,CURLOPT_URL,$url);
            curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
            curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);//最长执行时间
            curl_setopt($ch,CURLOPT_TIMEOUT,0);//最长等待时间
            curl_setopt($ch,CURLOPT_CUSTOMREQUEST,'GET');
            curl_setopt($ch,CURLOPT_HTTP_VERSION,'CURL_HTTP_VERSION_1_1');
            curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);
            curl_setopt($ch,CURLOPT_MAXREDIRS,10);
            curl_setopt($ch,CURLOPT_ENCODING,'');

            $img=curl_exec($ch);
            if (false === $img) {
                $ret = curl_errno($ch);
                write_log('downLoad', 'error', $ret);
            }
            curl_close($ch);
        }
        if($type===1){
            ob_start();
            readfile($url);
            $img=ob_get_contents();
            ob_end_clean();
        }
        if($type===2){
            $img=file_get_contents($url);
        }
        //判断下载的数据 是否为空 下载超时问题
        if(empty($img)){
            write_log('downLoad', 'error', $img);
            return 0;
//            throw new \Exception("下载错误,无法获取下载文件！");
        }

        //没有指定路径则默认当前路径
        if($path===''){
            $path="./";
        }

        //如果命名为空
        if($filename===""){
            $filename=md5($img);
        }

        //获取后缀名
        $ext=substr($url, strrpos($url, '.'));
        if($ext && strlen($ext)<5){
            $filename.=$ext;
        }

        //防止"/"没有添加
        $path=rtrim($path,"/")."/";
        //var_dump($path.$filename);die();
        $fp2=@fopen($path.$filename,'a');

        fwrite($fp2, $img);
        fclose($fp2);
        return 1;
    }
}
